/**
*****************************************************************************
 * @file step_motor.c
 * @brief 步进电机设备函数(步进电机、限位开关)
 * @author Moon
 * @version V1.0.0
 * @date 2022/09/04
****************************************************************************
 */
#include "main_task.h" 
#include "step_motor.h"
#include "A_shell.h"
#include "ParmManage.h"
#include "dev_tb67s109.h"
#include "func_StepMotor.h"
#include "drv_f4_gpioexit.h"
#include "drv_f4_delay_168MHz.h"
#include "drv_f4_delay_168MHz.h"
#include "timers.h"

static void run_callback(void *str);
static void step1_set_dir(uint8_t dir);
static int step1_set_step_run(uint32_t speed, uint32_t pluse);
static void step1_set_run_control(uint8_t control);

static void forward_limite_callback(void);
static void reverse_limite_callback(void);
uint8_t step1_limit_io_read(LIMITE_e limit);

dev_tb67s109_t step_drv =
{
    .PIN_MO = "E13",
    .PIN_STEP = "C8",
    .PIN_EN = "D9",
    .PIN_DIR = "D14",
    .PIN_RESET = "E15",

    .PWM_DRV = "TIM8",
    .TIMER_DRV = "TIM2",
    .pwm_Prescaler = 84-1, //84-1,
    .pwm_freq = 1250, // 500, //15000, //100000,(原始10000)
    .pwm_chx = TIMER_CH3,
    .pwm_clock_freq = 84000000,     //SYSCLK = 168MHz, APB1 Timer clock = 84MHz
    .timer_pluse = 0xFFFF,
    .PreempPriority = 6,

    .RunFinish_CallBack = run_callback,
    .DELAY_us = SoftDelayUs,
};

func_StepMotor_t StepMotor = 
{
    .step_workmode = STEP_NO_FEEDBACK_RUN,      //运动模式
    .unit_travel = 360,                         //丝杠导程
    .reduction_ratio = 1,                       //减速比
    .stepangle = 200,                           //步距角
    .subdivide = 32,                            //细分 
    .dir = Motor_Reverse,                       //运动方向
    .speed =  200, //, //70, // 140, //250,                                //速度10(转/min)
    .uniform_speed = 2,                         //短距离匀速速度(转/min)
    .scan_cnt = 60000,                          //单次扫描次数（从定时器最大状态值）
    .limit_polarity = 0,                        //限位开关低平触发
	
    .res_set_step_dir = step1_set_dir,
    .res_set_step_run = step1_set_step_run,
    .res_set_run_control = step1_set_run_control,
	.res_limit_io = step1_limit_io_read,
};

drv_gpioexit_t limit_io[LIMITE_NMU] = 
{
    [REVERSE_LIMITE] = 
	{
		.PIN = "E2", 
		.MODE = INPUT_UP, 
		.trigger = falling, 
		.PreempPriority = 5, 
		.callback = reverse_limite_callback,   //限位光耦外部中断回调函数绑定
	},
	[FORWARD_LIMITE] = 
	{
		.PIN = "E3", 
		.MODE = INPUT_UP, 
		.trigger = falling, 
		.PreempPriority = 5, 
		.callback = forward_limite_callback
	},
};

static uint8_t *soft_limit[LIMITE_NMU] = {NULL, NULL};

volatile uint8_t limit_flag = 3;//0是下限位，1是上限位
SemaphoreHandle_t xSemaphore_limit;
/* Private Struct ---------------------------------------------------------------*/
/* Private defines ---------------------------------------------------------------*/
/* Private enum ---------------------------------------------------------------*/

/* Private Variable ---------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

//Pointer
//Array
//Const

/***********************************************************************************
 * @brief 运动控制完成返回		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
static void run_callback(void*str)
{
    StepMotor.runover_callback(&StepMotor);
}

/***********************************限位开关处理函数********************************/
// 定义定时器句柄
TimerHandle_t xTimeoutStopTimer = NULL;

// 消抖定时器回调函数
static void vTimeoutStopTimerCallback(TimerHandle_t xTimer)
{
	BaseType_t pxHigherPriorityTaskWoken;
	// 定时器到期，此处执行消抖后的逻辑
	if(Motor_Forward == StepMotor.dir)
	{
		StepMotor.limit_callback(&StepMotor, FORWARD_LIMITE);

	}
	if(Motor_Reverse == StepMotor.dir)
	{
		StepMotor.limit_callback(&StepMotor, REVERSE_LIMITE);

	}
	xTimerStopFromISR(xTimeoutStopTimer,&pxHigherPriorityTaskWoken);
	data_server.motor.cmd = 0x03;	
}

/*******************************************************************
* 功能说明：创建软件定时器
* 输入参数：无
* 输出参数：TimerHandle_t xTimeoutStopTimer - 软件定时器
* 返回值：无
********************************************************************/
void vCreateTimeOutTimer()
{
	if (xTimeoutStopTimer == NULL) 
	{
		xTimeoutStopTimer = xTimerCreate("DebounceTimer", pdMS_TO_TICKS(80000), pdFALSE, (void *)0, vTimeoutStopTimerCallback);
		if (xTimeoutStopTimer == NULL) 
		{
			// 定时器创建失败，处理错误
			Ashell_print("stepmotor deounce timer creates fail.\r\n");
		}
	}
}

/***********************************************************************************
 * @brief 前进限位触发返回		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
static void forward_limite_callback(void)
{
	 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	
	if(data_server.motor.cmd == Motor_Forward)
	{
		StepMotor.limit_callback(&StepMotor, FORWARD_LIMITE);
		xSemaphoreGiveFromISR(xSemaphore_limit,&xHigherPriorityTaskWoken);
		data_server.motor.cmd = 0x3;	
	}
	xTimerStopFromISR(xTimeoutStopTimer,&xHigherPriorityTaskWoken);
	

}

/***********************************************************************************
 * @brief 后退限位触发返回		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
static void reverse_limite_callback(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;

	if((data_server.motor.cmd == Motor_Reverse))
	{
		StepMotor.limit_callback(&StepMotor, REVERSE_LIMITE);
        xSemaphoreGiveFromISR(xSemaphore_limit,&xHigherPriorityTaskWoken);
		data_server.motor.cmd = 0x3;	
	}
	xTimerStopFromISR(xTimeoutStopTimer,&xHigherPriorityTaskWoken);
}

/***********************************************************************************
 * @brief 软件限位-前进限位触发返回		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
void forward_soft_limite_callback(void)
{
	StepMotor.limit_callback(&StepMotor, FORWARD_LIMITE);
    Ashell_print("forward soft limite trigger.\r\n");
}

/***********************************************************************************
 * @brief 软件限位-后退限位触发返回		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
void reverse_soft_limite_callback(void)
{
	StepMotor.limit_callback(&StepMotor, REVERSE_LIMITE);
    Ashell_print("reverse soft limite trigger.\r\n");
}


/***********************************************************************************
 * @brief 限位状态读取	
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
uint8_t step1_limit_io_read(LIMITE_e limit)
{
    if (soft_limit[limit] != NULL)
	    return (limit_io[limit].Read(&limit_io[limit]) & *soft_limit[limit]);
    return limit_io[limit].Read(&limit_io[limit]);
}

/**********************************************************************************/
uint8_t get_motor_location(void)
{
	uint8_t st;
	if(0 != step1_limit_io_read(FORWARD_LIMITE) && 0 != step1_limit_io_read(REVERSE_LIMITE) && 1 == data_server.motor.cmd)
	{
		st = 0x01;
	}
	else if(0 != step1_limit_io_read(FORWARD_LIMITE) && 0 != step1_limit_io_read(REVERSE_LIMITE) && 2 == data_server.motor.cmd)
	{
		st = 0x02;
	}	
	else if(0 == step1_limit_io_read(FORWARD_LIMITE))
	{
		st = 0x03;
		
	}
	else if(0 == step1_limit_io_read(REVERSE_LIMITE))
	{
		st = 0x04;
	}
	else
	{
		st = 0x00;
	}
	return st;
}

/***********************************步进电机处理函数*********************************/
static void step1_set_dir(uint8_t dir)
{
    step_drv.set_step_dir(&step_drv, (TB67S109_DIR_e)dir);
}

static int step1_set_step_run(uint32_t speed, uint32_t pluse)
{
    return step_drv.set_step_run(&step_drv, speed, pluse);
}

static void step1_set_run_control(uint8_t control)
{
    step_drv.set_run_control(&step_drv, (TB67S109_CONTROL_e)control);
}
/**********************************************************************************/

/***********************************************************************************
 * @brief 软件限位注册	
 * ex:
 * @par flimit：前进限位 rlimit：后退限位
 * None
 * @retval void None
 **********************************************************************************/
void step_soft_limit_res(uint8_t *flimit, uint8_t *rlimit)
{
    soft_limit[FORWARD_LIMITE] = flimit;
    soft_limit[REVERSE_LIMITE] = rlimit;
}

static void StepMotorParameterInit(void)
{
//	uint8_t leave_factory = false;
//	leave_factory = PPGetInitFlag(PP_UNIT_TRAVEL);
//	if (leave_factory != 1)
//	{
//		PPItemIWrite(PP_UNIT_TRAVEL,     (uint8_t *)&StepMotor.unit_travel,         4); /* 丝杆导程	 */
//		PPItemIWrite(PP_SPEED,           (uint8_t *)&StepMotor.speed,               4); /* 速度 单位RPM 每分钟多少转 */
//		PPItemIWrite(PP_REDUCTION_RATIO, (uint8_t *)&StepMotor.reduction_ratio,     4); /* 减速比 */
//		PPItemIWrite(PP_SUBDIVIDE,       (uint8_t *)&StepMotor.subdivide,           2); /* 细分    驱动芯片细分 */		
//	}

//	PPItemRead(PP_UNIT_TRAVEL,     (uint8_t *)&StepMotor.unit_travel,               4); /* 导程	 */
//	PPItemRead(PP_SPEED,           (uint8_t *)&StepMotor.speed,                     4); /* 速度 单位RPM 每分钟多少转 */
//	PPItemRead(PP_REDUCTION_RATIO, (uint8_t *)&StepMotor.reduction_ratio,           4); /* 减速比 */
//	PPItemRead(PP_SUBDIVIDE,       (uint8_t *)&StepMotor.subdivide,                 2); /* 细分    驱动芯片细分 */
}

/***********************************************************************************
 * @brief 步进电机初始化		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
void step_motor_init(void)
{
	uint16_t i = 0;

    StepMotorParameterInit();
	
	if (Dev_Tb67s109_Init(&step_drv) < 0)
		while (1);
			
	if (Func_StepMotor_Init(&StepMotor) < 0)
		while (1);
			
	for (i = 0; i < LIMITE_NMU; i++)
	{
		if (Drv_GpioExit_Init(&limit_io[i]) < 0)
			while (1);	
		limit_io[i].Set(&limit_io[i], 1);
	}
	
	xSemaphore_limit = xSemaphoreCreateBinary();
	
	vCreateTimeOutTimer();       //创建软件定时器
}




static int step_info(uint8_t argc, char **argv)
{
    if (argc >= 2)
    {
        if (!strcmp(argv[1], "run"))
        {
            if (argc >= 3)
            {
                StepMotor.StepMotor_Set_Position_unit(&StepMotor, 0, atoi(argv[2]), RUN_ANGLE);
            }
            else
            {
                Ashell_print("Please input step <run angle>.\r\n");
            }
        }
    }
    else
    {
        Ashell_print("Please input step <run angle>.\r\n");
    }
    return 1;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), step, step_info, Stepper motor operation);
